//@author A0096509U
#pragma once
#ifndef TASKITSTORAGE_H_
#define TASKITSTORAGE_H_

#include "Task.h"
#include "PreviousAction.h"
#include "TaskItGlobal.h"
#include "Logger.h"
#include <stack>

//TaskItStorage is the Storage API for the programme. It is a container which stores all the necessary information
//and tasks that the user have added before. On top of that, it stores all the actions that the user have executed
//previously to modify the storage container since when the programme starts. This enables it to execute an undo function
//which is able to revert the container back to its original state before execution of that particular task.
class TaskItStorage {

private:
	vector <Task> _listOfTasks;
	int _numOfTask;
	PreviousAction _previousAction;
	stack <PreviousAction> _allPreviousActions;	
	string _myFileName;
	
	//This sort function is only and should only be called within the storage class. It sorts the tasks based on
	//this priority: 1) Floating Tasks, 2) Date, 3) Time. It is called after completing each action.
	//Pre-Req: None.
	//Post-Req: _listOfTasks should be sorted according to the given priority.
	void sortStorage(); 

public:
	TaskItStorage();

	//Reads the txt file "Storage.txt" which contains the whole list of tasks that the user have added and
	//adds it to _listOfTasks. This function is used to initialize storage when the user starts the programme.
	//Pre-Req: None.
	//Post-Req: Reads in all tasks in existing "Storage.txt" file. If it doesn't exist, it will bre created.
	void readFile();
	//Updates the "Storage.txt" file with the current tasks stored in _listOfTasks. This function should be called
	//each time after the container is being modified.
	//Pre-Req: None.
	//Post-Req: "Storage.txt" in local drive should contain the latest list of tasks of the user.
	void saveFile();

	//Task information input by user is temporarily added to a "Temp.txt" file when a clash of activity is found.
	//This is to facilitate the checking with user if he/she wants to confirm to add a task that clashes.
	//Pre-Req: Task details that are input by the user.
	//Post-Req: The respective details will be stored inside "Temp.txt".
	void addTempTask(string activity, string venue, TaskItTime timeStart, TaskItTime timeEnd, string category, Date date);
	//Adds in a conflicted task into _listOfTasks by taking the details from "Temp.txt". Returns true if there is a conflicted 
	//task to add.
	//Pre-Req: None.
	//Post-Req: Returns true when there are task details to add from "Temp.txt" and the task will be added. Else, when no task
	//			details are present in "Temp.txt" function will return false.
	void addConflictedTask(int &index);
	//This function clears the "Temp.txt" file when the user chooses not to add in a conflicted task. Returns true if the "Temp.txt" is
	//successfully truncated when there are task details inside or false when "Temp.txt" is already empty on start.
	//Pre-Req: None.
	//Post-Req: Returns true when there are contents inside "Temp.txt" and it is cleared successfull and false when "Temp.txt" is 
	//			already empty to begin with.
	void doNotAddConflictedTask();
	//This function adds a particular task given its details - activity, venue, timestart, timeend, category and date, to the current
	//_listOfTasks. Note that this does not check for any invalid input as it is assumed to be correct as inputs should be filtered
	//by TaskItScheduler.
	//Pre-Req: The 6 details of a task and given that it is a valid input to be added.
	//Post-Req: Task added to _listOfTasks and returns an integer representing the index that it is added to.
	int addTask(string activity, string venue, TaskItTime timeStart, TaskItTime timeEnd, string category, Date date);
	//Given an integer of the 1-base index, this function will delete that task from _listOfTasks. Note that it does not check for any
	//invalid inputs as blocks are implemented by TaskItScheduler.
	//Pre-Req: 1 - based index of the task to be deleted.
	//Post-Req: Deletes that particular task from _listOfTasks.
	void deleteTask(int numOfTask);
	//This function edits a particular task given its NEW details - activity, venue, timestart, timeend, category and date, to the current
	//one in _listOfTasks. Note that this does not check for any invalid input as it is assumed to be correct as inputs should be filtered
	//by TaskItScheduler.
	//Pre-Req: The 6 details of a task and its 1-based index of the task to be edited.
	//Post-Req: The slected task will be edited and returns an integer representing the index that it is added to.
	int editTask(string activity, string venue, TaskItTime timeStart, TaskItTime timeEnd, string category, Date date, int numOfTask);
	//Given an integer of the 1-base index, this function will mark that task done in _listOfTasks. Note that it does not check for any
	//invalid inputs as blocks are implemented by TaskItScheduler.
	//Pre-Req: 1-based index of the task to be marked done.
	//Post-Req: Marks that particular task from _listOfTasks.
	void markTask(int numOfTask);
	//Given an integer of the 1-base index, this function will unmark that task to be not done in _listOfTasks. Note that it does not check
	//for any invalid inputs as blocks are implemented by TaskItScheduler.
	//Pre-Req: 1-based index of the task to be marked undone.
	//Post-Req: Unmarks that particular task from _listOfTasks.
	void unMarkTask(int numOfTask);
	//Confirms a particular blocked slot to be the actual timing of the activity. Deletes any other instances of that activity. Note that
	//this does not consider invalid cases as it should be done by TaskItScheduler.
	//Pre-Req: The valid 1-based index of the task to be confirmed.
	//Post-Req: Confirms that task by removing the "Block:" and deletes any other instances of it.
	void confirm(int numOfTask);
	//Does a partial clear up of tasks inside _listOfTasks. This will delete past events that have already been marked done based
	//on the date of the local computer. Note that this function cannot be undone and its changes are not revertable.
	//Pre-Req: None.
	//Post-Req: Tasks that are done and before the local computer date will be deleted permanently.
	void clearTasks();
	//Undo a previous action that was done by the user by getting the information from the stack of previous actions. Will not do
	//anything if the stack is empty. 
	//Pre-Req: There is something to be undone.
	//Post-Req: Revert the action that was done depending on what the action was. E.g. If a task is deleted, it will be reinstated to
	//			its original position in _listOfTasks.
	void undoTask();
	
	//This is the getter function for the 0-based index of a particular task.
	//Pre-Req: A task that needs to be found if it exist in _listOfTasks.
	//Post-Req: Returns the integer of the index the task is located. -1 otherwise.
	int getTaskIndex(Task task);
	//This is the getter function to get all the task details in a single string of a specified task.
	//Pre-Req: The 0-based index of the task.
	//Post-Req: Returns a string with all details.
	string getTaskDetails(int index);
	//This is the getter function to get a Task given its index.
	//Pre-Req: 0-based index of the task in _listOfTasks.
	//Post-Req: Returns the Task as an object. Throws an invalid request otherwise.
	Task getTask(int index);
	//This is the getter function to get the total number of tasks.
	//Pre-Req: None.
	//Post-Req: Returns an integer of the number of tasks.
	int getNumOfTask();
	//This is the getter function to get the number of tasks with only an activity field.
	//Pre-Req: None.
	//Post-Req: Returns an integer with the number of tasks with only an activity field.
	int getNumOfFloatingTask();
	//This is the getter function to a vector of integers, containing all the dates inside the 
	//tasks that the user have added.
	//Pre-Req: None.
	//Post-Req: Dates will be converted to integers and returns as a vector of integers.
	vector <int> getDatesWithTasks();

	//This is to append any newline strings to the display string.
	//Pre-Req: Takes is an original string info.
	//Post-Req: Returns a string containing a newline at the rear.
	string showToUser(string info);
};

#endif

